﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Xsl;
using System.Xml.XPath;
using System.IO;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

namespace SQLServerFramework
{
    public partial class UtilityXml
    {
        [SqlMethod(
            IsDeterministic = true
            , IsPrecise = true
            , DataAccess = DataAccessKind.None
            , SystemDataAccess = SystemDataAccessKind.None
            , Name = "xslt_xml2xml"
        )]
        public static SqlXml XsltXml2Xml(SqlXml source, SqlXml transform, SqlXml transformParameters)
        {
            if (source.IsNull)
                return SqlXml.Null;

            if (transform.IsNull)
                return source;

            // load xslt
            XslCompiledTransform xslt = new XslCompiledTransform();
            xslt.Load(transform.CreateReader());
            
            // execute xslt
            using (MemoryStream ms = new MemoryStream())
            {
                xslt.Transform(source.CreateReader(), getXsltParameters(transformParameters), ms);
                ms.Flush();

                ms.Position = 0;
                return new SqlXml(ms);
            }
        }

        [return: SqlFacet(MaxSize = -1)]
        [SqlMethod(
            IsDeterministic = true
            , IsPrecise = true
            , DataAccess = DataAccessKind.None
            , SystemDataAccess = SystemDataAccessKind.None
            , Name = "xslt_xml2text"
        )]
        public static SqlString XsltXml2Text(SqlXml source, SqlXml transform, SqlXml transformParameters)
        {
            if (source.IsNull)
                return SqlString.Null;

            if (transform.IsNull)
                return SqlString.Null;

            // load xslt
            XslCompiledTransform xslt = new XslCompiledTransform();
            xslt.Load(transform.CreateReader());

            // execute xslt
            using (MemoryStream ms = new MemoryStream())
            {
                xslt.Transform(source.CreateReader(), getXsltParameters(transformParameters), ms);
                ms.Flush();

                return new SqlString(
                    System.Globalization.CultureInfo.CurrentCulture.LCID
                    , SqlCompareOptions.IgnoreCase | SqlCompareOptions.IgnoreKanaType | SqlCompareOptions.IgnoreWidth
                    , ms.ToArray()
                    , (xslt.OutputSettings.Encoding == Encoding.Unicode ? true : false)
                );
            }
        }

        private static XsltArgumentList getXsltParameters(SqlXml xsltParameters)
        {
            XsltArgumentList parameters = new XsltArgumentList();
            if (!xsltParameters.IsNull)
            {
                using (XmlReader reader = xsltParameters.CreateReader())
                {
                    while (reader.Read())
                    {
                        if (reader.Name == "param" && reader.IsStartElement())
                            parameters.AddParam(reader.GetAttribute(0), "", reader.ReadString());
                    }
                }
            }
            return parameters;
        }
    }
}
